package util

import (
	"github.com/gomodule/redigo/redis"
	jsoniter "github.com/json-iterator/go"
	"github.com/mix-go/dotenv"
	_ "mytest/dotenv"
	"time"
)

type redisUtil struct {
	Pool *redis.Pool
}

var Redigo *redisUtil

func init() {
	Redigo = &redisUtil{}
	Redigo.Pool = &redis.Pool{ //实例化一个连接池
		MaxIdle: 16, //最初的连接数量
		// MaxActive:1000000,    //最大连接数量
		MaxActive:   0,                                                                          //连接池最大连接数量,不确定可以用0（0表示自动定义），按需分配
		IdleTimeout: time.Duration(dotenv.Getenv("REDIS_DIAL_TIMEOUT").Int64(10)) * time.Second, //连接关闭时间 10秒 （10秒不使用自动关闭）
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", dotenv.Getenv("REDIS_ADDR").String())
			if err != nil {
				return nil, err
			}
			if _, err := c.Do("AUTH", dotenv.Getenv("REDIS_PASSWORD").String("")); err != nil {
				_ = c.Close()
				return nil, err
			}
			if _, err := c.Do("SELECT", dotenv.Getenv("REDIS_DATABASE").Int64(0)); err != nil {
				_ = c.Close()
				return nil, err
			}
			return c, nil
		},
	}
}

func (r *redisUtil) Set(key, value string) error {
	c := r.Pool.Get() //从连接池，取一个链接
	defer c.Close()   //函数运行结束 ，把连接放回连接池``
	_, err := c.Do("SET", key, value)
	return err
}

func (r *redisUtil) MSet(kvargs ...string) error {
	c := r.Pool.Get() //从连接池，取一个链接
	defer c.Close()   //函数运行结束 ，把连接放回连接池``
	_, err := c.Do("MSET", kvargs)
	return err
}

func (r *redisUtil) SetEx(key, value string, expire int) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("SET", key, value)
	if err != nil {
		return err
	}
	_, err = c.Do("EXPIRE", key, expire)
	if err != nil {
		return err
	}
	return nil
}

func (r *redisUtil) SetMap(key, value map[string]interface{}) error {
	json, _ := jsoniter.Marshal(value)
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("SET", key, json)
	return err
}

func (r *redisUtil) Get(key string) (value string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	value, err = redis.String(c.Do("GET", key))
	return
}

func (r *redisUtil) MGet(keys ...string) (values []string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	values, err = redis.Strings(c.Do("MGET", keys))
	return
}

func (r *redisUtil) Del(key string) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("DEL", key)
	return err
}

func (r *redisUtil) Lpush(key string, values ...interface{}) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("LPUSH", key, values)
	return err
}

func (r *redisUtil) Rpush(key, value string) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("RPUSH", key, value)
	return err
}

func (r *redisUtil) Lpop(key string) (value string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	value, err = redis.String(c.Do("LPOP", key))
	return value, err
}

func (r *redisUtil) Rpop(key string) (value string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	value, err = redis.String(c.Do("RPOP", key))
	return value, err
}

func (r *redisUtil) HSet(tableName, key string, value interface{}) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("HSET", tableName, key, value)
	return err
}

func (r *redisUtil) HGet(tableName, key string) (value string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	value, err = redis.String(c.Do("HGET", tableName, key))
	return
}

func (r *redisUtil) HMSet(tableName string, kvargs ...interface{}) error {
	c := r.Pool.Get()
	defer c.Close()
	_, err := c.Do("HMSET", tableName, kvargs)
	return err
}

func (r *redisUtil) HGetAll(tableName string) (value []string, err error) {
	c := r.Pool.Get()
	defer c.Close()
	value, err = redis.Strings(c.Do("HGETALL", tableName))
	return
}
